/********************************** (C) COPYRIGHT *******************************
* File Name          : foc_driver.c
* Author             : nx666
* Version            : V1.0.0
* Date               : 2023/02/27
* Description        : foc所依赖的mcu外设在这里实现接口.
*******************************************************************************/
/* 头文件区域 */
#include "driver.h"
#include "IQmathLib.h"
#include "ch32f20x.h"
#include "ch32f20x_tim.h"
#include "ch32f20x_gpio.h"
#include "debug.h"
#include "common_type.h"
#include "foc.h"
#include <stdio.h>
#include <string.h>
#include "malloc.h"


/* 宏定义区 */


/* 全局变量区 */

/*********************************************************************
 * @fn      workLedInit
 *
 * @brief   Initializes GPIOB.1
 *
 * @return  none
 */
static void workLedInit( void )
{
    GPIO_InitTypeDef  GPIO_InitStructure = {0};

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOB, &GPIO_InitStructure );
}

static void ledSetup(void)
{
    GPIO_WriteBit(GPIOB,GPIO_Pin_1,Bit_RESET);
}

static void ledDown(void)
{
    GPIO_WriteBit(GPIOB,GPIO_Pin_1,Bit_SET);
}

/*********************************************************************
 * @fn      workLedCreate
 *
 * @brief   创建工作灯
 *              void
 *
 * @return  成功，workLed *；  失败，NULL
 *          
 */
workLed_ *workLedCreate(void)
{
    workLed_ *p = NULL;
    workLedInit();
    p = (workLed_ *)malloc(sizeof(workLed_));
    if (!p)
    {
        return NULL;
    }
    memset((void *)p, 0, sizeof(workLed_));
    p->downLed = ledDown;
    p->setupLed = ledSetup;

    return p;
}



/*********************************************************************
 * @fn      timInit
 *
 * @brief   定时器初始化函数，
 *              outTime -定时器的超时时间  单位为1us 暂定1000，即超时时间为1ms
 *
 * @return  FUNC_SOK，成功  FUNC_FAIL，失败
 *          
 */
 static Int timInit(int outTime)
 {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = { 0 };
    uInt16 arr,psc;
    
    /* Enable timer3 clock */
    RCC_APB1PeriphClockCmd( RCC_APB1Periph_TIM3, ENABLE );

    /* 假设计数时钟为144M */
    arr = outTime;
    psc = 144;
    /* Initialize timer3 */
    TIM_TimeBaseInitStructure.TIM_Period = arr;
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc - 1;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit( TIM3, &TIM_TimeBaseInitStructure );

    /* Enable updating timer3 interrupt */
    TIM_ITConfig( TIM3, TIM_IT_Update, ENABLE );

    /* Configure timer3 interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init( &NVIC_InitStructure );

    /* Enable timer3 */
    TIM_Cmd( TIM3, ENABLE );

    /* Enable timer3 interrupt */
    NVIC_EnableIRQ( TIM3_IRQn );
    
    return FUNC_SOK;
 }

/*********************************************************************
 * @fn      focTimClearIrq
 *
 * @brief   foc定时器 中断清除函数.
 *
 * @param   void
 *         
 * @return  void
 */
static void focTimClearIrq(void)
{
    if( TIM_GetITStatus( TIM3, TIM_IT_Update ) != RESET )
    {
        /* Clear interrupt flag */
        TIM_ClearITPendingBit( TIM3, TIM_IT_Update );
        return;
    }
}

/*********************************************************************
 * @fn      focTimStart
 *
 * @brief   启动 foc定时器
 *
 * @param   void
 *         
 * @return  void
 */
static void focTimStart(void)
{
    timInit(FOC_TIM_OUTTIME);
}

/*********************************************************************
 * @fn      creatFocTim
 *
 * @brief   创建foc定时器.
 *
 * @param   void
 *         
 * @return  tim_ *，成功  NULL，失败
 */
tim_ *creatFocTim(void)
{
    tim_ *p = NULL;
    p = (tim_ *)malloc(sizeof(tim_));
    if (!p)
    {
        return NULL;
    }
    memset((void *)p, 0, sizeof(tim_));
    p->clearIrq = focTimClearIrq;
    p->startTim = focTimStart;

    return p;
}


static Int32 setSvpwmFrame(struct pwm *pTim,uInt16 a,uInt16 b,uInt16 c)
{
    pTim->frameCount++;
    pTim->pwmA = a;
    pTim->pwmB = b;
    pTim->pwmC = c;
    TIM_SetCompare1(TIM1,a);
    TIM_SetCompare2(TIM1,b);
    TIM_SetCompare3(TIM1,c);
    return 0;
}

/*********************************************************************
 * @fn      pwmInit
 *
 * @brief   初始化svpwm.
 *
 * @param   void
 *         
 * @return  FUNC_SOK，成功  FUNC_FAIL，失败
 */
static Int32 pwmInit( void )
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    TIM_OCInitTypeDef TIM_OCInitStructure = {0};
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = {0};
    TIM_BDTRInitTypeDef TIM_BDTRInitStruct = {0};
    uint16_t arr,psc;

    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA | RCC_APB2Periph_TIM1, ENABLE );
    /* 选择内部时钟为定时器时钟源 CK_INT 144M*/
    TIM_InternalClockConfig(TIM1);

    /* 配置输出管脚 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_10 | GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure );
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_Init( GPIOB, &GPIO_InitStructure );

    arr = PWM_DEFAULT_ARR;

    psc = (uint16_t)(144 * 1000000 / (arr * PWM_DEFAULT_FREQ));
    if (!psc)
    {
        psc = 1;
        PRINT_INFO("set TIM1.TIM_Prescaler = 1 \n");
    }
    TIM_TimeBaseInitStructure.TIM_Period = arr;
    TIM_TimeBaseInitStructure.TIM_Prescaler = psc - 1;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;          //核心计数器运行在增计数和减计数交替进行的模式下，OCxREF 
    TIM_TimeBaseInit( TIM1, &TIM_TimeBaseInitStructure );   //在核心计数器和比较捕获寄存器的值一致时进行上升和下降的跳变。
    

#if (PWM_MODE == PWM_MODE1)
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
#elif (PWM_MODE == PWM_MODE2)
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
#endif
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;     /*使能正通道输出输出*/
    TIM_OCInitStructure.TIM_Pulse = arr/2;                            /*设置捕获比较寄存器值*/
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;         /*设置正通道有效电平为高电平*/
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;   /*使能互补通道输出输出*/
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;        /*设置互补通道有效电平为高电平*/
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
    TIM_OC1Init( TIM1, &TIM_OCInitStructure ); /*如果 OCx 和 OCxN 都是高有效，那么 OCx 与 OCxREF 相同，OCxN 与 OCxREF 相反*/
    TIM_OC2Init( TIM1, &TIM_OCInitStructure );
    TIM_OC3Init( TIM1, &TIM_OCInitStructure );


    TIM_BDTRStructInit( &TIM_BDTRInitStruct );
    TIM_BDTRInitStruct.TIM_OSSIState = TIM_OSSIState_Disable;
    TIM_BDTRInitStruct.TIM_OSSRState = TIM_OSSRState_Disable;
    TIM_BDTRInitStruct.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
    TIM_BDTRInitStruct.TIM_DeadTime = (uint16_t)(1.0f * PWM_DEAD_TIME / PWM_DEFAULT_ARR * arr); /*设置死区时间*/
    TIM_BDTRInitStruct.TIM_Break = TIM_Break_Disable;
    TIM_BDTRInitStruct.TIM_BreakPolarity = TIM_BreakPolarity_High;
    TIM_BDTRInitStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
    printf("TIM_DeadTime[%d]\n",TIM_BDTRInitStruct.TIM_DeadTime);
    TIM_BDTRConfig( TIM1, &TIM_BDTRInitStruct );


    TIM_CtrlPWMOutputs( TIM1, ENABLE );               /*允许OCx和OCNx输出*/
#if 0
    TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Disable ); /*禁用比较寄存器的预装载寄存器,直接读写比较寄存器，立即生效*/
    TIM_OC2PreloadConfig( TIM1, TIM_OCPreload_Disable ); /*禁用比较寄存器的预装载寄存器,直接读写比较寄存器，立即生效*/
    TIM_OC3PreloadConfig( TIM1, TIM_OCPreload_Disable ); /*禁用比较寄存器的预装载寄存器,直接读写比较寄存器，立即生效*/
#else
    TIM_OC1PreloadConfig( TIM1, TIM_OCPreload_Enable ); /*使能比较寄存器的预装载寄存器,只能读写比较寄存器的预装载寄存器，下一个更新事件到来时生效*/
    TIM_OC2PreloadConfig( TIM1, TIM_OCPreload_Enable ); /*使能比较寄存器的预装载寄存器,只能读写比较寄存器的预装载寄存器，下一个更新事件到来时生效*/
    TIM_OC3PreloadConfig( TIM1, TIM_OCPreload_Enable ); /*使能比较寄存器的预装载寄存器,只能读写比较寄存器的预装载寄存器，下一个更新事件到来时生效*/
#endif
    TIM_ARRPreloadConfig( TIM1, ENABLE );             /*使能自动重装值寄存器（ATRLR）*/
    TIM_Cmd( TIM1, ENABLE );                          /*使能计数器*/

    return FUNC_SOK;
}

/*********************************************************************
 * @fn      creatFocTim
 *
 * @brief   创建foc定时器.
 *
 * @param   void
 *         
 * @return  tim_ *，成功  NULL，失败
 */
pwm_ *creatPwm(void)
{
    pwm_ *p = NULL;
    p = (pwm_ *)malloc(sizeof(pwm_));
    if (!p)
    {
        return NULL;
    }
    memset((void *)p, 0, sizeof(pwm_));

    pwmInit();

    p->deadTime = PWM_DEAD_TIME;
    p->frameCount = 0;
    p->frequency = PWM_DEFAULT_FREQ;
    p->set3PhasePwm = setSvpwmFrame;

    return p;
}

/*********************************************************************
 * @fn      adcDmaTxStart
 *
 * @brief   start the DMAy Channelx configuration.
 *
 * @param   DMA_CHx - x can be 1 to 7.
 *          ppadr - Peripheral base address.
 *          memadr - Memory base address.
 *          bufsize - DMA channel buffer size.
 *
 * @return  none
 */
static void adcDmaTxStart(uInt32 ppadr, uInt32 memadr, uInt16 bufsize )
{
    DMA_Channel_TypeDef *DMAy_Channelx = (DMA_Channel_TypeDef *)DMA1_Channel1;

    DMA_Cmd( DMA1_Channel1, DISABLE );

    DMAy_Channelx->CNTR = bufsize;
    DMAy_Channelx->MADDR = memadr;
    DMAy_Channelx->PADDR = ppadr;

    DMA_ITConfig( DMA1_Channel1, DMA_IT_TC | DMA_IT_TE, ENABLE );

    DMA_Cmd( DMA1_Channel1, ENABLE );
}

/*********************************************************************
 * @fn      adcDmaTxInit
 *
 * @brief   Initializes the DMAy Channelx configuration.
 *
 * @param   DMA_CHx - x can be 1 to 7.
 *          ppadr - Peripheral base address.
 *          memadr - Memory base address.
 *          bufsize - DMA channel buffer size.
 *
 * @return  none
 */
static void adcDmaTxInit(uInt32 ppadr, uInt32 memadr, uInt16 bufsize )
{
    DMA_InitTypeDef DMA_InitStructure = {0};
    //NVIC_InitTypeDef NVIC_InitStructure = {0};

    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );

    DMA_DeInit( DMA1_Channel1 );
    DMA_InitStructure.DMA_PeripheralBaseAddr = ppadr;
    DMA_InitStructure.DMA_MemoryBaseAddr = memadr;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_BufferSize = bufsize;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init( DMA1_Channel1, &DMA_InitStructure );


    // NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
    // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    // NVIC_Init( &NVIC_InitStructure );

    // DMA_ITConfig( DMA1_Channel1, DMA_IT_TC | DMA_IT_TE, ENABLE );

}

/*********************************************************************
 * @fn      DMA1_Channel1_IRQHandler
 *
 * @brief   DMA1_Channel1_IRQHandler Interrupt Service Function.
 *
 * @return  none
 */
// void DMA1_Channel1_IRQHandler()
// {
//     DMA_Channel_TypeDef *DMAy_Channelx = (DMA_Channel_TypeDef *)DMA1_Channel1;
//     if( DMA_GetITStatus( DMA1_IT_TC1 ) == SET )
//     {
//         DMA_ClearITPendingBit( DMA1_IT_TC1 );

//         DMA_Cmd( DMA1_Channel1, DISABLE );

//         DMAy_Channelx->CNTR = bufsize;

//         DMA_Cmd( DMA1_Channel1, ENABLE );
        
//         return;
//     }

//     if( DMA_GetITStatus( DMA1_IT_TE1 ) == SET )
//     {
//         DMA_ClearITPendingBit( DMA1_IT_TE1 );
//         return;
//     }
// }

/*********************************************************************
 * @fn      adcInit
 *
 * @brief   初始化adc，采样线电流
 *
 * @param   void
 *         
 * @return  FUNC_SOK，成功  FUNC_FAIL，失败
 */
static Int32 adcInit(adc_ *pAdc)
{
	ADC_InitTypeDef ADC_InitStructure={0};
	GPIO_InitTypeDef GPIO_InitStructure={0};

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE );
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2, ENABLE );
	RCC_ADCCLKConfig(RCC_PCLK2_Div8);

	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	ADC_DeInit(ADC1);
    ADC_DeInit(ADC2);

	ADC_InitStructure.ADC_Mode = ADC_Mode_RegSimult;
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;
	ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
	ADC_InitStructure.ADC_NbrOfChannel = 1;
    ADC_InitStructure.ADC_OutputBuffer = ADC_OutputBuffer_Disable;
    ADC_InitStructure.ADC_Pga = ADC_Pga_1;

	ADC_Init(ADC1, &ADC_InitStructure);
    ADC_RegularChannelConfig( ADC1, ADC_Channel_0, 1, ADC_SampleTime_71Cycles5 );
    ADC_DMACmd( ADC1, ENABLE );                     //使能 DMA 模式
    ADC_Cmd( ADC1, ENABLE );                        //当该位为 0 时，写入 1 将把 ADC 从断电模式下唤醒

    ADC_BufferCmd( ADC1, DISABLE ); //disable buffer
    ADC_ResetCalibration( ADC1 );                           // 初始化校准寄存器
    while( ADC_GetResetCalibrationStatus( ADC1 ) );
    ADC_StartCalibration( ADC1 );
    while( ADC_GetCalibrationStatus( ADC1 ) );
    pAdc->calibrattionVal1 = Get_CalibrationValue( ADC1 );

    ADC_Init( ADC2, &ADC_InitStructure );
    ADC_RegularChannelConfig( ADC2, ADC_Channel_1, 1, ADC_SampleTime_71Cycles5 );

    ADC_SoftwareStartConvCmd( ADC2, ENABLE );
    ADC_Cmd( ADC2, ENABLE );                        //当该位为 0 时，写入 1 将把 ADC 从断电模式下唤醒

    ADC_BufferCmd( ADC2, DISABLE ); //disable buffer
    ADC_ResetCalibration( ADC2 );
    while( ADC_GetResetCalibrationStatus( ADC2 ) );
    ADC_StartCalibration( ADC2 );
    while( ADC_GetCalibrationStatus( ADC2 ) );
    pAdc->calibrattionVal2 = Get_CalibrationValue( ADC2 );

    pAdc->adcValBuf = (uInt32 *)malloc(DMA_BUF_LEN * sizeof(uInt32));
    if (!pAdc->adcValBuf)
    {
        return -1;
    }
    memset(pAdc->adcValBuf, 0 ,DMA_BUF_LEN * sizeof(uInt32));

    adcDmaTxInit(( uInt32 )&ADC1->RDATAR,( uInt32 )pAdc->adcValBuf,pAdc->bufLen);

    DMA_Cmd( DMA1_Channel1, ENABLE );
    ADC_SoftwareStartConvCmd( ADC1, ENABLE );

    return 0;
}

// /*********************************************************************
//  * @fn      adcStartWithDMA
//  *
//  * @brief   启动adc采样，并采用dma传输
//  *
//  * @param   pAdcDev - adc对象.
//  *         
//  * @return  FUNC_SOK，成功  FUNC_FAIL，失败
//  */
// Int32 adcStartWithDMA(foc_adcObj   *pAdcDev)
// {
//     if (!pAdcDev)
//     {
//         PRINT_EER(" pAdcDev is null\n");
//         return FUNC_FAIL;
//     }
//     adcDmaTxStart(( uInt32 )&ADC1->RDATAR,( uInt32 )pAdcDev->adcValBuf,pAdcDev->bufLen);
//     ADC_SoftwareStartConvCmd( ADC1, ENABLE );
//     return FUNC_SOK;
// }

// /*********************************************************************
//  * @fn      waitAdcDmaReady
//  *
//  * @brief   等待adc转换和dma传输完成
//  *
//  * @param   void
//  *         
//  * @return  FUNC_SOK，完成  FUNC_FAIL，失败
//  */
// Int32 waitAdcDmaReady(void)
// {
//     Int count = 0;
//     DMA_Channel_TypeDef *pDMA1_Channel1 = (DMA_Channel_TypeDef *)DMA1_Channel1;
//     while(count++ < 1000)
//     {
//         if (0 == pDMA1_Channel1->CNTR)
//         {
//             return FUNC_SOK;
//         }
//         Delay_Us(1);
//     }
//     return FUNC_FAIL;
// }
// /*********************************************************************
//  * @fn      adcStop
//  *
//  * @brief   停止adc采样
//  *
//  * @param   pAdcDev - adc对象.
//  *         
//  * @return  FUNC_SOK，成功  FUNC_FAIL，失败
//  */
// Int32 adcStop(foc_adcObj   *pAdcDev)
// {
//     if (!pAdcDev)
//     {
//         return FUNC_FAIL;
//     }
//     ADC_SoftwareStartConvCmd( ADC1, DISABLE );
//     return FUNC_SOK;
// }

/*********************************************************************
 * @fn      getCurrentI
 *
 * @brief   从dma缓存里读出adc数据，并计算出线电流.
 *
 * @param   void
 *         
 * @return  0，成功  -1，失败
 */
static Int getCurrentI(struct adc * pAdc)
{
    _iq     adc1Sum =0;
    _iq     adc2Sum =0;
    _iq     cSum =0;
    Int     temp;
    Int     i;
    uInt16 *p;

    // ADC_TypeDef *ADCx = ADC1;
    // DMA_Channel_TypeDef *DMAy_Channelx = DMA1_Channel1;

    p = (uInt16 *)pAdc->adcValBuf;
    for (i=0;i<pAdc->bufLen;i++)
    {
        /* 小端模式，低地址保存数据高位，高位是adc2的转换数据 */
        *p += pAdc->calibrattionVal1;
        adc1Sum += *p;
        p++;

        *p += pAdc->calibrattionVal2;
        adc2Sum += *p;
        
        p++;
    }

    // IC + IB + IA = 0
    temp = (FOC_SAMPLING_V_ZERO_A + FOC_SAMPLING_V_ZERO_B + FOC_SAMPLING_V_ZERO_C) << FOC_SAMPLING_ARRAY_LEN;
    cSum = temp - (adc1Sum + adc2Sum);

    pAdc->Ia = _IQ8mpy(pAdc->convertK1, _IQ8(adc1Sum)) + pAdc->convertK2_a;
    pAdc->Ib = _IQ8mpy(pAdc->convertK1, _IQ8(adc2Sum)) + pAdc->convertK2_b;
    pAdc->Ic = _IQ8mpy(pAdc->convertK1, _IQ8(cSum)) + pAdc->convertK2_c;

    //mA --> A
    pAdc->Ia = (pAdc->Ia >> 10);
    pAdc->Ib = (pAdc->Ib >> 10);
    pAdc->Ic = (pAdc->Ic >> 10);

    return 0;
}

/*********************************************************************
 * @fn      createAdc
 *
 * @brief   创建adc.
 *
 * @param   void
 *         
 * @return  adc_ *，成功  NULL，失败
 */
adc_ *createAdc(void)
{
    adc_ *p = NULL;
    float convertK2;
    p = (adc_ *)malloc(sizeof(adc_));
    if (!p)
    {
        return NULL;
    }
    memset((void *)p, 0, sizeof(adc_));

    p->getCurrentIaIbIc = getCurrentI;
    p->adcBitWidth = FOC_SAMPLING_ADC_WIDTH;
    p->bufLen = 0x1 << FOC_SAMPLING_ARRAY_LEN;
    p->refV = FOC_SAMPLING_VREF_V;

    // I = （adcSum / 采样窗口大小 / 4096 * refV - 0点电压） / 采样电流芯片放大系数 / 采样电阻 毫欧
    // I adc * convertK1  + convertK2
    //故 convertK1 = 1000 / (采样窗口大小 * 4096 * 采样电流芯片放大系数 * 采样电阻)
    //convertK2 = -(1000 * 0点电压 / (采样电流芯片放大系数 * 采样电阻))
    p->convertK1 = p->bufLen * ((0x1 << FOC_SAMPLING_ADC_WIDTH) -1) * FOC_SAMPLING_CHIP_GAIN * FOC_SAMPLING_RS;
    p->convertK1 = _IQ8((float)1000 * FOC_SAMPLING_VREF_V / p->convertK1);
    convertK2 = FOC_SAMPLING_CHIP_GAIN * FOC_SAMPLING_RS;
    p->convertK2_a = -_IQ8((float)(FOC_SAMPLING_V_ZERO_A * 1000) / convertK2);
    p->convertK2_b = -_IQ8((float)(FOC_SAMPLING_V_ZERO_B * 1000) / convertK2);
    p->convertK2_c = -_IQ8((float)(FOC_SAMPLING_V_ZERO_C * 1000) / convertK2);
    
    adcInit(p);

    return p;
}

/*********************************************************************
 * @fn      serialDmaInit
 *
 * @brief   Configures the DMA for USART2
 *
 * @return  none
 */
static void serialDmaInit( void )
{
    DMA_InitTypeDef DMA_InitStructure = {0};

    RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );

    DMA_DeInit( DMA1_Channel7 );
    DMA_InitStructure.DMA_PeripheralBaseAddr = ( u32 )( &USART2->DATAR ); /* USART2->DATAR:0x40004404 */
    DMA_InitStructure.DMA_MemoryBaseAddr = ( u32 )0;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_BufferSize = 0;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
    DMA_Init( DMA1_Channel7, &DMA_InitStructure );

    DMA_DeInit( DMA1_Channel6 );
    DMA_InitStructure.DMA_PeripheralBaseAddr = ( u32 )( &USART2->DATAR );
    DMA_InitStructure.DMA_MemoryBaseAddr = ( u32 )0;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_BufferSize = 0;
    DMA_Init( DMA1_Channel6, &DMA_InitStructure );
}

/*********************************************************************
 * @fn      USART2_IRQClear
 *
 * @brief   清除usart2空闲中断标记中断标记.
 *
 * @param   
 *
 * @return  返回dma传输的数据字节计数
 */
int USART2_idleIRQClear()
{
    int temp;
    USART_TypeDef *pUSARTx = (USART_TypeDef *)USART2;
    DMA_Channel_TypeDef *pDMA1_Channel6 = (DMA_Channel_TypeDef *)DMA1_Channel6;

    if( USART_GetITStatus( USART2, USART_IT_IDLE ) == SET )
    {
        USART_ClearITPendingBit( USART2, USART_IT_IDLE );
        temp = pUSARTx->STATR; //先读STATR，再读DATAR才会清除
        temp = pUSARTx->DATAR;
        return pDMA1_Channel6->CNTR;
    }
}


/*********************************************************************
 * @fn      serialInit
 *
 * @brief   Initializes the USARTx peripheral.
 *
 * @param   baudrate - USART communication baud rate.
 *
 * @return  None
 */
void serialInit(u32 baudrate)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;	
    USART_Init(USART2, &USART_InitStructure); 
    USART_Cmd(USART2, ENABLE);

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init( &NVIC_InitStructure );

    USART_ITConfig( USART2, USART_IT_IDLE, ENABLE );

    //USART_DMACmd( USART2, USART_DMAReq_Rx, ENABLE );

    //DMA_Cmd( DMA1_Channel6, ENABLE );                                  /* USART2 Rx */

    serialDmaInit();
}

/*********************************************************************
 * @fn      uartSend
 *
 * @brief   uart发送一段数据.
 *
 * @param   pBuffer - 数据地址. size - 待发送数据的长度
 *
 * @return  None
 */
void uartSend(uInt8 *pBuffer, int size)
{
    DMA_Channel_TypeDef *pDMA1_Channel7 = (DMA_Channel_TypeDef *)DMA1_Channel7;
    if (!pBuffer)
    {
        return;
    }
    while(pDMA1_Channel7->CNTR){};
    DMA_Cmd( DMA1_Channel7, DISABLE );
    pDMA1_Channel7->CNTR = size;
    pDMA1_Channel7->MADDR = (uInt32)pBuffer;
    DMA_Cmd( DMA1_Channel7, ENABLE );                                  /* USART2 Tx */
    USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);
}


/*********************************************************************
 * @fn      uartRecv
 *
 * @brief   uart开启接收数据.
 *
 * @param   pBuffer - 数据保存地址. size - 可使用的缓存的长度
 *
 * @return  None
 */
void uartRecv(uInt8 *pBuffer, int size)
{
    DMA_Channel_TypeDef *pDMA1_Channel6 = (DMA_Channel_TypeDef *)DMA1_Channel6;
    if (!pBuffer)
    {
        return;
    }
    DMA_Cmd( DMA1_Channel6, DISABLE );
    pDMA1_Channel6->CNTR = size;
    pDMA1_Channel6->MADDR = (uInt32)pBuffer;
    DMA_Cmd( DMA1_Channel6, ENABLE );                                  /* USART2 Tx */
    USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);
}

/*********************************************************************
 * @fn      logSend
 *
 * @brief   发送一段log.
 *
 * @param   pBuffer - log地址. size - 待发送log的长度
 *
 * @return  None
 */
void logSend(uInt8 *pBuffer, int size)
{
    uartSend(pBuffer,size);
}





